/*
 * 版权所有 (c) 华为技术有限公司 2022-2022
 */
package com.huawei.cameratest;

import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.ImageFormat;
import android.graphics.Rect;
import android.hardware.Camera;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.util.Range;
import android.util.Size;
import android.view.View;
import android.widget.*;

import com.huawei.cameratest.data.CameraCharacteristicsEx;
import com.huawei.cameratest.data.StreamView;
import com.huawei.cameratest.util.StreamConfigDB;

import java.util.ArrayList;
import java.util.List;

public class MultiImageReaderSettingActivity extends Activity {
    public static final String ID = "ID";
    public static final String RESOLUTION = "RESOLUTION";
    public static final String PREVIEW = "PREVIEW";
    public static final String STREAM_NUMBER = "STREAM_NUMBER";
    public static final String SET_FPS = "SET_FPS";

    private String TAG = this.getClass().getSimpleName();
    private Spinner camera_spinner;
    private Spinner resolution_spinner;
    private Spinner FPS_spinner;
    private Spinner overlay_spinner;
    private Spinner streams_spinner;
    private Spinner preview_spinner;
    private StreamView streamView0;
    private StreamView streamView1;
    private StreamView streamView2;
    private StreamView streamView3;

    private LinearLayout linearLayoutForStream0;
    private LinearLayout linearLayoutForStream1;
    private LinearLayout linearLayoutForStream2;
    private LinearLayout linearLayoutForStream3;

    private Button btnStart;
    private Button ptzTestButton;

    private String[] streamsList = new String[]{"0", "1", "2", "3", "4"};
    private String[] isPreview = new String[]{"false", "true"};

    private CameraManager cameraManager;
    private CameraCharacteristics cameraCharacteristics;
    private StreamConfigurationMap streamConfigurationMap;
    private String[] ids;
    private String CameraId = "0";
//    public static Size[] resolutions;
    public static final Size[] resolutions = new Size[] {
        new Size(3840, 2160),
        new Size(2560, 1440),
        new Size(1920, 1080),
        new Size(1280, 720),
        new Size( 960, 540),
        new Size( 848, 480),
        new Size( 800, 600),
        new Size( 800, 448),
        new Size( 640, 480),
        new Size( 640, 360),
        new Size( 480, 360),
        new Size( 480, 270),
        new Size( 424, 240),
        new Size( 320, 240),
        new Size( 320, 180),
        new Size( 256, 144),
        new Size( 160, 90),
        // for test
        new Size(1111, 888),
    };
    private Range[] ranges;
    private String[] FPS;
    private String fps;
    private Integer[] svcModes;

    boolean isH264Camera = false;
    boolean isH265Camera = false;

    private static final String[] PERMISSIONS_ARRAY = new String[]
            {
                    Manifest.permission.CAMERA,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE,
                    Manifest.permission.RECORD_AUDIO
            };

    CameraManager.AvailabilityCallback availabilityCallback = new CameraManager.AvailabilityCallback() {
        @Override
        public void onCameraAvailable(String cameraId) {
            Log.i(TAG, "onCameraAvailable: ");
            // 插上
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    long start = System.currentTimeMillis();
                    // getCameraStatus();
                    long end = System.currentTimeMillis();
                    Log.i(TAG, "run 111: " + (end - start));
                }
            });
        }

        @Override
        public void onCameraUnavailable(String cameraId) {
            Log.i(TAG, "onCameraUnavailable: " + cameraId);
            // 拔下
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    long start = System.currentTimeMillis();
                    // getCameraStatus();
                    long end = System.currentTimeMillis();
                    Log.i(TAG, "run 222: " + (end - start));
                }
            });
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        checkRequiredPermission(this);
        setContentView(R.layout.activity_multi_image_reader_setting);
        initView();
        initCameraId();
        initEvent();
        cameraManager.registerAvailabilityCallback(availabilityCallback, null);
    }

    @Override
    protected void onRestart() {
        super.onRestart();
    }

    private void checkRequiredPermission(final Activity activity) {
        List<String> permissionsList = new ArrayList<String>();

        for (String permission : PERMISSIONS_ARRAY) {
            if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) {
                permissionsList.add(permission);
            }
        }

        if (permissionsList.size() > 0) {
            ActivityCompat.requestPermissions(activity,
                    permissionsList.toArray(new String[permissionsList.size()]), 1);
        }
    }

    private void initView() {
        camera_spinner = findViewById(R.id.Spinner_camera);
        camera_spinner.setBackgroundResource(R.drawable.selector_spinner);
        camera_spinner.setClickable(false);
        resolution_spinner = findViewById(R.id.Spinner_resolution);
        resolution_spinner.setBackgroundResource(R.drawable.selector_spinner);
        FPS_spinner = findViewById(R.id.Spinner_FPS_id);
        FPS_spinner.setBackgroundResource(R.drawable.selector_spinner);
        streams_spinner = findViewById(R.id.Spinner_steams_id);
        streams_spinner.setBackgroundResource(R.drawable.selector_spinner);
        preview_spinner = findViewById(R.id.Spinner_preview_id);
        preview_spinner.setBackgroundResource(R.drawable.selector_spinner);
        linearLayoutForStream0 = findViewById(R.id.linear_stream0_id);
        linearLayoutForStream1 = findViewById(R.id.linear_stream1_id);
        linearLayoutForStream2 = findViewById(R.id.linear_stream2_id);
        linearLayoutForStream3 = findViewById(R.id.linear_stream3_id);

        streamView0 = new StreamView(
                findViewById(R.id.Spinner_stream0_resolution_id),
                findViewById(R.id.Spinner_stream0_encodeBitrate_id),
                findViewById(R.id.Spinner_stream0_iframeInterval_id),
                findViewById(R.id.Spinner_stream0_qualityParam1_id),
                findViewById(R.id.Spinner_stream0_qualityParam2_id),
                findViewById(R.id.Spinner_stream0_requestIFrame_id),
                findViewById(R.id.Spinner_stream0_svcMode_id),
                findViewById(R.id.Spinner_stream0_format_id),
                MultiImageReaderSettingActivity.this
        );
        streamView1 = new StreamView(
                findViewById(R.id.Spinner_stream1_resolution_id),
                findViewById(R.id.Spinner_stream1_encodeBitrate_id),
                findViewById(R.id.Spinner_stream1_iframeInterval_id),
                findViewById(R.id.Spinner_stream1_qualityParam1_id),
                findViewById(R.id.Spinner_stream1_qualityParam2_id),
                findViewById(R.id.Spinner_stream1_requestIFrame_id),
                findViewById(R.id.Spinner_stream1_svcMode_id),
                findViewById(R.id.Spinner_stream1_format_id),
                MultiImageReaderSettingActivity.this
        );
        streamView2 = new StreamView(
                findViewById(R.id.Spinner_stream2_resolution_id),
                findViewById(R.id.Spinner_stream2_encodeBitrate_id),
                findViewById(R.id.Spinner_stream2_iframeInterval_id),
                findViewById(R.id.Spinner_stream2_qualityParam1_id),
                findViewById(R.id.Spinner_stream2_qualityParam2_id),
                findViewById(R.id.Spinner_stream2_requestIFrame_id),
                findViewById(R.id.Spinner_stream2_svcMode_id),
                findViewById(R.id.Spinner_stream2_format_id),
                MultiImageReaderSettingActivity.this
        );
        streamView3 = new StreamView(
                findViewById(R.id.Spinner_stream3_resolution_id),
                findViewById(R.id.Spinner_stream3_encodeBitrate_id),
                findViewById(R.id.Spinner_stream3_iframeInterval_id),
                findViewById(R.id.Spinner_stream3_qualityParam1_id),
                findViewById(R.id.Spinner_stream3_qualityParam2_id),
                findViewById(R.id.Spinner_stream3_requestIFrame_id),
                findViewById(R.id.Spinner_stream3_svcMode_id),
                findViewById(R.id.Spinner_stream3_format_id),
                MultiImageReaderSettingActivity.this
        );

        btnStart = (Button) findViewById(R.id.btnStart);
        btnStart.setOnClickListener(btnStartClick);

        ptzTestButton = findViewById(R.id.ptzTest);
        ptzTestButton.setOnClickListener(ptzTestClick);
    }

    private void initCameraId() {
        try {
            cameraManager = (CameraManager) MultiImageReaderSettingActivity.this.getSystemService(CAMERA_SERVICE);
            ids = cameraManager.getCameraIdList();
            // camera id
            ArrayAdapter cameraAdapter = new ArrayAdapter(MultiImageReaderSettingActivity.this,
                    android.R.layout.simple_spinner_item, ids);
            cameraAdapter.setDropDownViewResource(R.layout.new_spinner_background);
            camera_spinner.setAdapter(cameraAdapter);
            for (int i = 0; i < ids.length; i++) {
                if (CameraId.equals(ids[i])) {
                    camera_spinner.setSelection(i);
                    break;
                }
            }
            String useId = camera_spinner.getSelectedItem().toString();
            if (!CameraId.equals(useId)) {
                Toast.makeText(MultiImageReaderSettingActivity.this, "camera disconnect!",
                        Toast.LENGTH_SHORT).show();
                MultiImageReaderSettingActivity.this.finish();
            }
            initData(CameraId);
        } catch (CameraAccessException e) {
            Toast.makeText(MultiImageReaderSettingActivity.this, "no camera!", Toast.LENGTH_SHORT).show();
            MultiImageReaderSettingActivity.this.finish();
        }
    }

    private void initOverlaySpinner() {
        ArrayList<String> overlayMode = new ArrayList<String>();
        overlayMode.add("false");
        try {
            Byte supportOverlay = (Byte) cameraCharacteristics.get(CameraCharacteristicsEx.PREVIEW_VIA_VO_SUPPORTED);
            if (supportOverlay == 1) {
                Log.i(TAG, "support overlay.");
                overlayMode.add("true");
            } else if (supportOverlay == 0) {
                Log.i(TAG, "not support overlay.");
            } else {
                Log.e(TAG, "overlay tag return a error value.");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        ArrayAdapter overlayAdapter = new ArrayAdapter(MultiImageReaderSettingActivity.this,
                android.R.layout.simple_spinner_item, overlayMode);
        overlayAdapter.setDropDownViewResource(R.layout.new_spinner_background);
        overlay_spinner.setAdapter(overlayAdapter);
        overlay_spinner.setSelection(0);
    }

    private void initStreams() {
        // stream number
        ArrayAdapter streamsAdapter = new ArrayAdapter(MultiImageReaderSettingActivity.this,
                android.R.layout.simple_spinner_item, streamsList);
        streamsAdapter.setDropDownViewResource(R.layout.new_spinner_background);
        streams_spinner.setAdapter(streamsAdapter);
    }

    private void initPreviewSpinner() {
        ArrayAdapter previewAdapter = new ArrayAdapter(MultiImageReaderSettingActivity.this,
                android.R.layout.simple_spinner_item, isPreview);
        previewAdapter.setDropDownViewResource(R.layout.new_spinner_background);
        preview_spinner.setAdapter(previewAdapter);
        preview_spinner.setSelection(1);
    }

    private void initData(String Id) {
        try {
            cameraCharacteristics = cameraManager.getCameraCharacteristics(Id);
            streamConfigurationMap = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);

            // resolution

//            resolutions = streamConfigurationMap.getOutputSizes(ImageFormat.JPEG);
            ArrayList strings = new ArrayList();
            for (int i = 0; i < resolutions.length; i++) {
                Size size = resolutions[i];
                strings.add(size.toString());
                Log.i(TAG, "support resolution:" + size.toString());
            }
            ArrayAdapter resolutionAdapter = new ArrayAdapter(MultiImageReaderSettingActivity.this,
                    android.R.layout.simple_spinner_item, strings);
            resolutionAdapter.setDropDownViewResource(R.layout.new_spinner_background);
            resolution_spinner.setAdapter(resolutionAdapter);
            resolution_spinner.setSelection(strings.size() - 1);
            // FPS
            ranges = cameraCharacteristics.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES);
            if (ranges != null) {
                FPS = new String[ranges.length];
                for (int i = 0; i < FPS.length; i++) {
                    FPS[i] = ranges[i].toString();
                    Log.i(TAG, "support FPS:" + ranges[i].toString());
                }
                fps = FPS[FPS.length - 1];
            }
            ArrayAdapter fpsAdapter = new ArrayAdapter(MultiImageReaderSettingActivity.this,
                    android.R.layout.simple_spinner_item, FPS);
            fpsAdapter.setDropDownViewResource(R.layout.new_spinner_background);
            FPS_spinner.setAdapter(fpsAdapter);
            for (int i = 0; i < FPS.length; i++) {
                if (fps.equals(FPS[i])) {
                    FPS_spinner.setSelection(i);
                }
            }
            try {
                svcModes = (Integer[]) cameraCharacteristics.get(CameraCharacteristicsEx.H264_SVC_MODES);
                if (svcModes != null) {
                    Log.i(TAG, "svc Mode size " + svcModes.length);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            initStreams();
            initPreviewSpinner();

            checkCamera();
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    private void checkCamera() {
        try {
            Integer[] int1 = (Integer[]) cameraCharacteristics.get(
                    CameraCharacteristicsEx.HAL_CUSTOM_CAMERA_H264_AVAILABLE_STREAM_CONFIGURATIONS);
            if (int1 != null) {
                for (int i = 0; i < int1.length; i++) {
                    Log.i(TAG, "h264AvailableStreamConfigurations " + int1[i]);
                }
                isH264Camera = true;
                Log.i(TAG, "checkCamera:h264 support");
            }
        } catch (Exception e) {
            isH264Camera = false;
        }
        try {
            Integer[] int2 = (Integer[]) cameraCharacteristics.get(
                    CameraCharacteristicsEx.HAL_CUSTOM_CAMERA_H265_AVAILABLE_STREAM_CONFIGURATIONS);
            if (int2 != null) {
                isH265Camera = true;
                Log.i(TAG, "checkCamera:h265 support");
            }
        } catch (Exception e) {
            isH265Camera = false;
        }
    }

    private void initEvent() {
        camera_spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                initData(parent.getSelectedItem().toString());
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            }
        });
        streams_spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                LinearLayout[] linearLayouts = new LinearLayout[]{linearLayoutForStream0, linearLayoutForStream1, linearLayoutForStream2, linearLayoutForStream3};
                StreamView[] streamViews = new StreamView[]{streamView0, streamView1, streamView2, streamView3};
                for (int i = 0; i < linearLayouts.length; i++) {
                    linearLayouts[i].setVisibility(View.GONE);
                }
                for (int i = 0; i < Integer.parseInt(parent.getSelectedItem().toString()); i++) {
                    streamViews[i].initStreamValue(streamConfigurationMap, i, svcModes);
                    linearLayouts[i].setVisibility(View.VISIBLE);
                }
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            }
        });
    }

    private View.OnClickListener btnStartClick = new View.OnClickListener() {
        @Override
        public void onClick(View mView) {
            Intent intent = new Intent(MultiImageReaderSettingActivity.this, MultiImageReaderActivity.class);
            StreamConfigDB.getInstance().clearDb();
            String streamNumber = streams_spinner.getSelectedItem().toString();
            intent.putExtra(ID, camera_spinner.getSelectedItem().toString());
            intent.putExtra(RESOLUTION, resolution_spinner.getSelectedItem().toString());
            intent.putExtra(SET_FPS, FPS_spinner.getSelectedItem().toString());
            intent.putExtra(PREVIEW, preview_spinner.getSelectedItem().toString());
            intent.putExtra(STREAM_NUMBER, streamNumber);
            if (Integer.valueOf(streamNumber) > 0) {
                StreamConfigDB.getInstance().storeStreamConfig(new StreamView[]{streamView0, streamView1, streamView2, streamView3}, Integer.valueOf(streamNumber));
            }
            Log.i(TAG, "start MultiImageReaderActivity");
            startActivity(intent);
        }
    };

    private View.OnClickListener ptzTestClick = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            try {
                Rect activeRect = (Rect) cameraCharacteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
                int type = (int) cameraCharacteristics.get(CameraCharacteristics.SCALER_CROPPING_TYPE);
                float maxZoom = (float) cameraCharacteristics.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM);
                Log.i(TAG,"ptzTest: CameraCharacteristics.get! activeRect(" + activeRect + ") type(" + type + ") maxZoom("+ maxZoom + ")");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };

    @Override
    protected void onDestroy() {
        cameraManager.unregisterAvailabilityCallback(availabilityCallback);
        super.onDestroy();
    }
}